package modele;

import java.io.Writer;
import java.rmi.server.UnicastRemoteObject;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;


public class PropositionImpl extends UnicastRemoteObject implements Proposition {

	/**
	 * 
	 */
	private static final long serialVersionUID = 6L;
	Dossier me;
	Date date;
	Parcours parcours;
	SortedSet<UniteEnseignement> uesChoix1, uesChoix2;
	String reponse;              // "OUI +", "OUI", "NON +", "-" [Aucune]
	// la reponse "Retire" est geree globalement dans le dossier

	public PropositionImpl(Dossier dos, Date date) throws Exception {
		me = dos;
		this.date = date;
		parcours = null;
		uesChoix1 = new TreeSet<UniteEnseignement>(new ComparatorUE());
		uesChoix2 = new TreeSet<UniteEnseignement>(new ComparatorUE());
		reponse = "-";
	}

	// les assesseurs
	public Date getDate() throws Exception {
		return date;
	}

	public Parcours getParcours() throws Exception {
		return parcours;
	}

	public SortedSet<UniteEnseignement> getUesChoix1() throws Exception {
		return uesChoix1;
	}

	public SortedSet<UniteEnseignement> getUesChoix2() throws Exception {
		return uesChoix2;
	}

	public String getReponseCoupon() throws Exception {
		return reponse;
	}

	public void setDate() throws Exception {
		date = new Date();
	}

	public void setDate(Date d) throws Exception {
		date = d;
	}

	public void setParcours(Parcours p) throws Exception {
		parcours = p;
	}

	public boolean addUesChoix1(UniteEnseignement ue) throws Exception {
		return uesChoix1.add(ue);
	}

	public boolean addUesChoix2(UniteEnseignement ue) throws Exception {
		return uesChoix2.add(ue);
	}

	public void setReponseCoupon(String st) throws Exception {
		reponse = st;
	}

	/** Pour faire une copie d'une ancienne proposition
	 *  on nettoie la presente
	 *  on recopie la proposition
	 **/
	public void setProposition(Proposition prop) throws Exception {
		clear();
		parcours = prop.getParcours();
		if (parcours != null) {
			for (UniteEnseignement ue : parcours.getUeObligatoires())
				ue.addProposition(me);
			for (UniteEnseignement ue : prop.getUesChoix1()) {
				ue.addProposition(me);
				uesChoix1.add(ue);
			}
			for (UniteEnseignement ue : prop.getUesChoix2()){
				ue.addProposition(me);
				// un ajout pour afficher les incompatibilites
				//				if (!ue.isCompatible(parcours.getUeObligatoires()) || !ue.isCompatible(uesChoix1) || !ue.isCompatible(uesChoix2)){
				//					Writer file=new BufferedWriter(new OutputStreamWriter(new FileOutputStream("Donnees/ueConflitEdt.txt"), "ISO-8859-1"));
				//
				//					file.write(me.getIdent()+", "+ue.getSigle()+", ");
				//					imprimerRetenuTexteUes(file);
				//					file.close();
				//				}
				uesChoix2.add(ue);
			}
			parcours.addProposition(me);
		}
	}

	// les algos

	private void clear() throws Exception {
		if (parcours != null){
			for (UniteEnseignement ue : parcours.getUeObligatoires())
				ue.removeProposition(me);
			for (UniteEnseignement ue : uesChoix1)
				ue.removeProposition(me);
			for (UniteEnseignement ue : uesChoix2)
				ue.removeProposition(me);
			parcours.removeProposition(me);
			parcours = null;
			uesChoix1.clear();
			uesChoix2.clear();
		}
	}

	public int[] valeur(Demande demande) throws Exception {
		// la proposition est toujours valide au moment de sa creation
		// depuis la demande peu avoir changee
		// elle ne l'est donc pas toujours
		List<Fiche> fiches = demande.getFiches();
		int[] valeur = new int[15]; // pour coder la valeur de la proposition
		for (int i=0; i<valeur.length; i++) // valeur parcours et des UE
			valeur[i]=0;
		boolean trouveP = false;
		for (Fiche fic : fiches) {
			if(!trouveP) {
				valeur[0]++;
				Parcours par = fic.getParcours();
				if (par == parcours){
					trouveP = true;
					int ind = 1+par.getNbUeObligatoires();
					// les ue obligatoires
					for (int i=1; i<ind; i++)
						valeur[i]=1;
					// choix 1
					int indFic = 1;
					for (UniteEnseignement ue : fic.getUesChoix1()) {
						// dans l'ordre de la demande
					//	boolean trouveUE = false;
						for (UniteEnseignement uec : uesChoix1) {
							//if(!trouveUE){
								// dans l'ordre des ue
								if (ue == uec){
						//			trouveUE = true;
									System.out.println("Demande : "+demande.getDossier().getEtudiant().getIdApoflux());
									valeur[ind] = indFic;
									ind++;
									break;
								}
							//}
						}
						indFic++;
					}
					// au cas ou il n'y aurait plus assez d'ue au choix
					int ind2 = 1+par.getNbUeObligatoires()+par.getNbUeChoix1();
					for (; ind<ind2; ind++)
						valeur[ind]=9;
					// Choix 2
					indFic = 1;
					for (UniteEnseignement ue : fic.getUesChoix2()){
						// dans l'ordre de la demande
						boolean trouveUE = false;
						for (UniteEnseignement uec : uesChoix2) {
							if(!trouveUE) {
								// dans l'ordre des ue
								if (ue == uec){
									trouveUE = true;
									valeur[ind] = indFic;
									ind++;
								}
							}
						}
						indFic++;
					}
					// au cas ou il n'y aurait plus assez d'ue choix 2
					for (; ind<valeur.length; ind++)
						valeur[ind] = 9;//uesLibre.size()+1;
				}
			}
		}
		return valeur;
	}

	/** compare deux propositions par rapport a une demande et retourne
	 *  0 si identique
	 *  1 si celle-ci est meilleure
	 *  -1 si celle passee en parametre est meilleure
	 **/
	public int compareTo(Proposition prop, Demande demande) throws Exception {
		if (prop.isValide())
			if (isValide()) {
				int[] valeurProp = prop.valeur(demande);
				int[] valeurMe = valeur(demande);
				for (int i=0; i<valeurMe.length; i++)
					if (valeurMe[i] < valeurProp[i])
						return 1;
					else if (valeurMe[i] > valeurProp[i])
						return -1;
				return 0;
			}
			else
				return -1;
		else if (isValide())
			return 1;
		else
			return 0;
	}

	public boolean isRetenu() throws Exception {
		return (reponse.equals("OUI +")|
				reponse.equals("OUI")|
				reponse.equals("-"));
	}

	public boolean isValide() throws Exception {
		// le parcours TMP est toujours valide
		if (parcours != null &&
				(parcours.getSigle().startsWith("Enseirb")|
						parcours.getSigle().startsWith("Non"))) {
			return true;
		}
		return (parcours != null &&
				uesChoix1.size() == parcours.getNbUeChoix1() &&	uesChoix2.size() == parcours.getNbUeChoix2());
	}

	/** calcule une nouvelle proposition a partir de la fiche en parametre
	 **/
	public boolean affecter(Fiche fic) throws Exception {
		clear();
		parcours = fic.getParcours();
		if (parcours.addProposition(me)){ // quota Parcours
			int nbUe=0;
			// les UE obligatoires
			for (UniteEnseignement ue : parcours.getUeObligatoires()) {
				System.out.print("Essai affectation ue "+ue.getIntitule()+" (quota:"+ue.getQuota()+") : ");;
				if (ue.addProposition(me)) { // quota UE
					nbUe++;
					System.out.println("ok");
				}
				else
					System.out.println("Echec");
			}
			if (nbUe == parcours.getNbUeObligatoires()) {
				// les UE au choix
				System.out.println("UE obligatoires ok");
				nbUe=0;
				for (UniteEnseignement ue : fic.getUesChoix1()) {
					if(nbUe<parcours.getNbUeChoix1()){
						if (ue.addProposition(me)){ // quota UE
							uesChoix1.add(ue);
							nbUe++;
						}
					}
				}
				nbUe=0;
				if (uesChoix1.size() == parcours.getNbUeChoix1()) {
					System.out.println("UE choix 1 ok");
					for (UniteEnseignement ue : fic.getUesChoix2()) {
						if(nbUe<parcours.getNbUeChoix2()){
							if (ue.addProposition(me)){ // quota UE
								uesChoix2.add(ue);
								nbUe++;
							}
						}
					}
					if (uesChoix2.size()==parcours.getNbUeChoix2()) {
						// affectation reussie
						System.out.println("UE choix 2 ok");
						System.out.println("Parcours affecté : "+parcours.getIntitule());
						return true;
					}
					System.out.println("Parcours non affecté (pb ue choix2) : "+parcours.getIntitule());
					clear();
					return false;
				}
				System.out.println("Parcours non affecté (pb ue choix1) : "+parcours.getIntitule());
				clear();
				return false;
			}
			System.out.println("Parcours non affecté (pb ue obligatoires (quota)) : "+parcours.getIntitule());
			clear();
			return false;
		}
		System.out.println("Parcours non affecté (quota parcours) : "+parcours.getIntitule());
		clear();
		return false;
	}

	// les sorties
	public void imprimer(Writer file) throws Exception {
		int nb_voeu=0;
		for(Fiche f : me.getDemande().getFiches()) {
			if(f.getParcours().getSigle().equals(parcours.getSigle())) {
				nb_voeu=f.getIndiceChoix()+1;
				break;
			}
		}
		SimpleDateFormat df = new SimpleDateFormat("dd/MM/yy");
		Etudiant etu = me.getEtudiant();
		file.write(df.format(date)+"&"+etu.getIdApoflux()+"&"+etu.getNom()+"&"+
				etu.getPrenom()+"&"+etu.getEtablissementOrigine()+"&"+
				me.getNoteDossier()+"&"+
				parcours.toString()+"&"+uesChoix1.toString()+"&"+uesChoix2.toString()+"&"+
				"V\\oe{}u "+Integer.toString(nb_voeu)+"&"+me.getReponseCoupon()+"\\\\\n\\hline\n");
	}

	public void imprimerAffichage(Writer file) throws Exception {
		Etudiant etu = me.getEtudiant();
		file.write(etu.getNom()+"&"+etu.getPrenom()+"&"+
				etu.getIdApoflux()+"&"+parcours.toString()+"&"+
				uesChoix1.toString()+"&"+uesChoix2.toString()+"\\\\\n\\hline\n");
	}

	public void imprimerCourrier(Writer file, boolean premier)
	throws Exception {
		int[] valeur = valeur(me.getDemande());
		//if (me.isFirstProposition(this))
		if (premier) // C'est le premier global et non sa premiere proposition
			file.write("La ");
		else
			file.write("Suite \\`a des d\\'esistements, la ");
		file.write("commission de recrutement du master 2 informatique a "+
				"le plaisir de vous annoncer que, "+
				"{\\bf sous r\\'eserve de la fourniture de l'attestation de réussite au "+
				"Master 1} elle");
		switch(valeur[0]) {
		case 1 : file.write(" a retenu votre premier choix et");break;
		case 2 : file.write(" a retenu votre second choix et");break;
		case 3 : file.write(" a retenu votre troisi\\`eme choix et");break;
		case 4 : file.write(" a retenu votre quatri\\`eme choix et");break;
		case 5 : file.write(" a retenu votre cinqui\\`eme choix et");break;
		case 6 : file.write(" a retenu votre sixi\\`eme choix et");break;
		case 7 : file.write(" a retenu votre septi\\`eme choix et");break;
		default : file.write("");
		}
		file.write(" vous propose le parcours suivant~:\n"+
				"\\begin{longtable}{|l|}\n"+
				"\\caption*{\\bf{"+parcours.getIntitule()+"}}\\\\\n");
		if (parcours.getUeObligatoires().size() > 0) {
			file.write("\\hline\n"+
			"\\multicolumn{1}{|c|}{UE obligatoire}\\\\\n");
			for (UniteEnseignement ue : parcours.getUeObligatoires()) {
				file.write(ue.getIntitule()+"\\\\\n");
			}
		}
		if (uesChoix1.size() > 0) {
			file.write("\\hline\n"+
			"\\multicolumn{1}{|c|}{UE choix 1}\\\\\n");
			for (UniteEnseignement ue : uesChoix1) {
				file.write(ue.getIntitule()+"\\\\\n");
			}
		}
		if (uesChoix2.size() > 0) {
			file.write("\\hline\n"+
			"\\multicolumn{1}{|c|}{UE choix 2}\\\\\n");
			for (UniteEnseignement ue : uesChoix2)
				file.write(ue.getIntitule()+"\\\\\n");
		}
		file.write("\\hline\n\\end{longtable}\n");
	}

	public void imprimerDossier(Writer file) throws Exception {
		file.write("\\caption*{{\\bf Parcours "+parcours.getIntitule()+"}}\\\\\n");
		int nb=0;
		for (UniteEnseignement ue : parcours.getUeObligatoires()){
			if (nb==0)
				file.write("Unit\\'es obligatoires&"+ue.getIntitule()+"\\\\\n");
			else
				file.write("&"+ue.getIntitule()+"\\\\\n");
			nb++;
		}
		nb = 0;
		for (UniteEnseignement ue : uesChoix1) {
			if (nb==0)
				file.write("Unit\\'es choix 1&"+ue.getIntitule()+"\\\\\n");
			else
				file.write("&"+ue.getIntitule()+"\\\\\n");
			nb++;
		}
		nb = 0;
		for (UniteEnseignement ue : uesChoix2) {
			if (nb==0)
				file.write("Unit\\'es choix 2&"+ue.getIntitule()+"\\\\\n");
			else
				file.write("&"+ue.getIntitule()+"\\\\\n");
			nb++;
		}
		file.write("\\hline\n");
	}

	public void imprimerRetenuTexteBibli(Writer file) throws Exception {
		// seul les retenus sont imprimes
		if (isRetenu()) {
			Etudiant etu = me.getEtudiant();
			file.write(etu.getIdApoflux()+", "+
					etu.getNom()+", "+
					etu.getPrenom()+", "+
					((Fiche)me.getDemande().getFiches().get(0)).getParcours().getSigle()+"\n");
		}
	}

	public void imprimerRetenuTexteUes(Writer file) throws Exception {
		// seul les retenus sont imprimes
		if (isRetenu() && !parcours.getSigle().startsWith("Non")) {
			SortedSet<UniteEnseignement> ues = new TreeSet<UniteEnseignement>(new ComparatorUE());
			ues.addAll(parcours.getUeObligatoires());
			ues.addAll(uesChoix1);
			ues.addAll(uesChoix2);
			Etudiant etu = me.getEtudiant();
			file.write(etu.getIdApoflux()+", "+etu.getNom()+", "+etu.getPrenom()+", "+parcours.getSigle()+", "+ues);
		}
	}
}
